#include "../../ExEngine/math/matrix.h"

#include "../../ExEngine/physics/actor.h"
#include "../../ExEngine/physics/physics.h"
#include "../../ExEngine/math/quaternion.h"
#include "../../ExEngine/common/util.h"
#include "../../ExEngine/engine/engine.h"
#include "../../ExEngine/engine/object.h"
#include "../../ExEngine/engine/camera.h"
#include "../../ExEngine/render/d3d_mesh.h"
#include "../../ExEngine/render/d3d.h"
#include "../../ExEngine/sound/dsound.h"
#include "../../ExEngine/input/dinput.h"

#include "crate.h"
#include "player.h"
#include "../game/core.h"

const float DURATION = 1.7525f;
const float MUZZLE = 0.005f;
const float OFFSHOOT = 0.5f;

/**********************************************************************
 *
 **********************************************************************/

CCrate::CCrate() : CObject()
{
	m_isValid = true;
}

HRESULT CCrate::Create()
{	
	if(FAILED(CEngine::GetInstance()->GetRenderer()->CreateModel("crate.mdl", &m_pModel)))
	{
		Release();
		return E_FAIL;
	}

	CActor::ActorData data;
	data.initalTransform = m_transform;
	data.angularDampening = 10.0f;
	data.maxAngularSpeed = 0.0f;
	data.mass = 1000.0f;
	data.friction = 10.0f;
	data.restitution = 0.05f;
	data.maxForce = 100.0f;
	data.maxSlope = 10.0f;

	if(FAILED(CEngine::GetInstance()->GetPhysics()->CreateActor("crate.HKX", &m_pPhysics, data, this)))
	{
		Release();
		return E_FAIL;
	}

	m_pPhysics->SetResponceToObject(Game::g_Player, CActor::UNAFFECTED);
	m_pPhysics->SetCollisionCallback(this);
	m_pModel->setRenderFlags(RENDER_DEFAULT);


	return S_OK;
}

HRESULT CCrate::Release()
{	
	HRESULT result = S_OK;
	if(m_pModel)
	{
		m_pModel = NULL;
	}
	if(m_pPhysics)
	{
		CPhysics* pPhysics = CEngine::GetInstance()->GetPhysics();
		if(FAILED(pPhysics->ReleaseActor(m_pPhysics)))
			result = E_FAIL;
		m_pPhysics = NULL;
	}
	return result;
}

void CCrate::Idle()
{
}

void CCrate::setPosition(const Vector3f &position)
{
	m_transform = Matrix4f::identity();
	m_transform.SetTranslation(position); 
	if(m_pPhysics)
		m_pPhysics->SetTransform(m_transform);
	
}
void CCrate::OnCollisionEvent(const Vector3f& contactPoint, const Vector3f& contactNormal, CObject* pOtherObject) {

	if(pOtherObject == Game::g_Player)
	{
		Vector3f contNormal = contactNormal;
		const float impactAngle = Vector3f::dot(&contNormal, &Vector3f(0,1,0));
		if(impactAngle > 0.8f) {

			const float impactMagnitude = Vector3f::dot(&Game::g_Player->GetVelocity(), &contNormal);
			if(fabs(impactMagnitude) > 10.0f) {
				Vector3f p = contNormal;
				//CEngine::GetInstance()->GetRenderer()->WriteLine(ScreenText::DEFAULT_FACE, "CN = %f,%f,%f", p.x, p.y,p.z);

				m_isValid = false;
			}
		}

		//MessageBox(0,0,0,0);
	}

//	
}

bool CCrate::isValid() {
	return m_isValid;
}

void CCrate::UpdateTransform()
{
	if(m_pPhysics) {
		
		m_transform = m_pPhysics->GetTransform();
	}
}

void CCrate::Update(const float dt)
{	
		/*
	Vector3f p = getPosition();
	CEngine::GetInstance()->GetRenderer()->WriteLine(ScreenText::ERROR_FACE, "%f,%f,%f", p.x, p.y,p.z);*/
	/************************************************************
	 * Event detection and firing
	 */
	CallEvent(&CCrate::Idle);

	UpdateTransform();
}

void CCrate::Draw()
{	
	if(m_pModel) {

		m_pModel->Draw(m_transform,m_velocity);

	}

}